package file.sftp;

import cn.hutool.core.io.IoUtil;
import com.jcraft.jsch.SftpException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author guoqf
 */
public class GzFileUtils {

    private static String ip = "10.1.198.67";
    private static int port = 22;

    private static String user = "ng4a";

    private static String pwd = "Wolf@2022";


    public static void main(String[] args) {
        String remoteDir = "/home/ng4a/tsnTest";

        String remoteFile = "testFile.tar.gz";


        RemoteFileInfo fileInfo = new RemoteFileInfo();
        fileInfo.setFileServiceIp(ip);
        fileInfo.setFileServicePort(port);
        fileInfo.setFileServiceUser(user);
        fileInfo.setFileServicePwd(pwd);
        fileInfo.setFileDir(remoteDir);
        fileInfo.setFileNames(Collections.singletonList(remoteFile));
        List<String> dataList = downloadData(fileInfo);

        System.out.println("下载json文件：");
        System.out.println(dataList);
//        readSftpFiles(remoteDir, Collections.singletonList(remoteFile));
    }


    public static String extractTarGzipFile(Path source, String target)
            throws IOException {

        if (Files.notExists(source)) {
            throw new IOException("File doesn't exists!");
        }

        try (InputStream fi = Files.newInputStream(source);
             BufferedInputStream bi = new BufferedInputStream(fi);
             GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
             TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {

            ArchiveEntry entry;
            while ((entry = ti.getNextEntry()) != null) {

                // create a new path, zip slip validate
//                Path newPath = zipSlipProtect(entry, target);

                String name = entry.getName();
                if (name.equals(target)) {

                    return IoUtil.read(ti, StandardCharsets.UTF_8);
                }

            }
        }

        return "";
    }


    public static String extractTarGzipFile(InputStream fi, String target)
            throws IOException {
        try (BufferedInputStream bi = new BufferedInputStream(fi);
             GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
             TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {

            ArchiveEntry entry;
            while ((entry = ti.getNextEntry()) != null) {

                // create a new path, zip slip validate
//                Path newPath = zipSlipProtect(entry, target);

                String name = entry.getName();
                if (name.equals(target)) {

                    return IoUtil.read(ti, StandardCharsets.UTF_8);
                }

            }
        }

        return "";
    }


    public static String extractJsonFile(InputStream fi) throws IOException {

        try (BufferedInputStream bi = new BufferedInputStream(fi);
             GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
             TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {

            ArchiveEntry entry;
            while ((entry = ti.getNextEntry()) != null) {

                // create a new path, zip slip validate
//                Path newPath = zipSlipProtect(entry, target);

                String name = entry.getName();

                if (name.endsWith(".json")) {

                    return IoUtil.read(ti, StandardCharsets.UTF_8);
                }

            }
        }

        return "";
    }

    private static void readSftpFiles(String dir, List<String> fileNames) {
        SFtpUtil sftpUtil = new SFtpUtil(ip, port, user, pwd);
        boolean connect = sftpUtil.connect();
        if (connect) {
            System.out.println("SFTP服务器连接成功");
            for (String fileName: fileNames) {
                try (InputStream download = sftpUtil.download(fileName, dir)) {
                    String s = extractJsonFile(download);
                    System.out.println("下载json文件成功");
                    System.out.println(s);
                } catch (SftpException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        }else {
            System.out.println("SFTP服务器连接失败");
        }


    }


    private static List<String> downloadData(RemoteFileInfo fileInfo) {
        TsnFileServer sftpUtil = new TsnFileServer(fileInfo.getFileServiceIp(), fileInfo.getFileServicePort(), fileInfo.getFileServiceUser(), fileInfo.getFileServicePwd());
        boolean connect = sftpUtil.connect();
        List<String> dataList = new ArrayList<>();
        if (connect) {
            try {
                System.out.println("SFTP服务器连接成功");
                List<String> fileNames = fileInfo.getFileNames();
                String fileDir = fileInfo.getFileDir();
                for (String fileName: fileNames) {
                    try (InputStream download = sftpUtil.download(fileName, fileDir)) {
                        String s = extractJsonFile(download);
                        System.out.println("下载json文件成功");
                        System.out.println(s);
                        dataList.add(s);
                        System.out.println("删除文件");
                        sftpUtil.remove(fileName, fileDir);
                        System.out.println("删除文件成功");
                    } catch (SftpException e) {
                        throw new RuntimeException(e);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            } finally {
                sftpUtil.disconnect();
            }

        }else {
            System.out.println("SFTP服务器连接失败");
        }
        return dataList;
    }
}
